package com.atguigu.gmall.order.reciver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.Service.OrderInfoService;
import com.atguigu.gmall.payment.client.PaymentFeignClient;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @program: gmall-parent
 * @author: Mr.Zhuo
 * @create: 2022-04-20 18:01
 **/
@Component
public class OrderReceiver {


    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PaymentFeignClient paymentFeignClient;

    /**
     * 减完库存，回发给订单模块消息
     *
     * @param msgJson
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            key = {MqConst.ROUTING_WARE_ORDER}
    ))
    public void updateOrderStatus(String msgJson, Message message, Channel channel) throws IOException {


        try {
            if (msgJson != null) {
                // 将传过来的数据转换成map  取出来数据
                Map map = JSON.parseObject(msgJson, Map.class);

                // 然后获取对应的数据
                String orderId = (String) map.get("orderId");
                String status = (String) map.get("status");
                if ("DEDUCTED".equals(status)) {
                    // 然后修改订单的物流状态
                    orderInfoService.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.DELEVERED);
                } else {
                    // 修改订单的物流状态
                    orderInfoService.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.STOCK_EXCEPTION);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    /**
     * 支付之后，异步回调，通知订单修改状态
     *
     * @param orderId
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            key = {MqConst.ROUTING_PAYMENT_PAY}
    ))
    public void updateOrderStatus(Long orderId, Message message, Channel channel) throws IOException {
        try {
            OrderInfo orderInfo = orderInfoService.getById(orderId);
            if (orderInfo != null && "UNPAID".equals(orderInfo.getProcessStatus()) && "UNPAID".equals(orderInfo.getOrderStatus())) {
                // 进行修改orderInfo的状态
                orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);

                // 首先发送消息给仓库进行发货
                orderInfoService.sendOrderStatus(orderId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认消息 如果不确认，有可能会到消息残留。
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    /**
     * 异步接受生成订单的时候的消息，如果二十四小时支付将自动把支付状态变为close
     *
     * @param orderId
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_ORDER_CANCEL, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, arguments = {
                    @Argument(name = "x-delayed-type", value = "direct")
            }, type = "x-delayed-message"),
            key = {MqConst.ROUTING_ORDER_CANCEL}
    ))
    public void cancelOrder(Long orderId, Message message, Channel channel) throws IOException {

        //  判断当前订单Id 不能为空
        try {
            if (orderId != null) {
                //  发过来的是订单Id，那么你就需要判断一下当前的订单是否已经支付了。
                //  未支付的情况下：关闭订单
                //  根据订单Id 查询orderInfo select * from order_info where id = orderId
                //  利用这个接口IService  实现类ServiceImpl 完成根据订单Id 查询订单信息 ServiceImpl 类底层还是使用的mapper
                OrderInfo orderInfo = orderInfoService.getById(orderId);
                //  判断支付状态,进度状态
                if (orderInfo != null && "UNPAID".equals(orderInfo.getOrderStatus())
                        && "UNPAID".equals(orderInfo.getProcessStatus())) {
                    //  关闭订单
                    //orderInfoService.execExpiredOrder(orderId);
                    PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());

                    if (paymentInfo != null && "UNPAID".equals(paymentInfo.getPaymentStatus())) {
                        // 判断当前是否有交易记录
                        Boolean flag = paymentFeignClient.checkPayment(orderId);
                        if (flag) {
                            // 关闭支付
                            Boolean aBoolean = paymentFeignClient.closePay(orderId);
                            if (aBoolean) {
                                // 关闭订单
                                orderInfoService.execExpiredOrder(orderId, "2");
                            } else {
                                // 说明现在客户已经支付  不需要关闭
                            }
                        } else {
                            orderInfoService.execExpiredOrder(orderId, "2");
                        }
                    } else {
                        orderInfoService.execExpiredOrder(orderId, "1");
                    }
                }
            }
        } catch (Exception e) {
            //  消息没有正常被消费者处理： 记录日志后续跟踪处理!
            // 如果出现异常，也会进行下面的消息确定
            e.printStackTrace();
        }
        //  手动确认消息 如果不确认，有可能会到消息残留。
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

}

